﻿using System;
using System.Collections.Generic;
using System.IO;

namespace Log.Recorder
{
    /// <summary>
    /// 日志器池
    /// </summary>
    sealed class DbWriterPool
    {
        /// <summary>
        /// 
        /// </summary>
        private static DateTime DestroyTime = DateTime.Now;
        /// <summary>
        /// 日志器池  ( logFileName , 日志器 )
        /// </summary>
        private static Dictionary<string, DbWriter> WriterPool = new Dictionary<string, DbWriter>();

        /// <summary>
        /// 日志器池大小
        /// </summary>
        public static int WriterCount
        {
            get {
                return WriterPool.Count;
            }
        }

        /// <summary>
        /// 获取数据库连接字符串
        /// </summary>
        /// <param name="logFilePath">路径。如  2021\\06\\13\\20210613_debug.db</param>
        /// <returns></returns>
        public static string GetConnectionStringByLogType(string logFilePath)
        {
            string logFileFolderPath = Path.GetDirectoryName(LogConfig.LogDbPathRoot + logFilePath);
            if (!Directory.Exists(logFileFolderPath))
            {
                Directory.CreateDirectory(logFileFolderPath);
            }

            return string.Format(@"Data Source={0}{1};Pooling=true;Max Pool Size=100;"
                , LogConfig.LogDbPathRoot
                , logFilePath);
        }

        /// <summary>
        /// 判断记录器是否在池中
        /// </summary>
        /// <param name="logFilePath">路径。如  2021\\06\\03\\20210603_debug.db</param>
        /// <returns></returns>
        public static bool IsHasWriter(string logFilePath) {
            string logFileName = Path.GetFileName(logFilePath);
            return WriterPool.ContainsKey(logFileName);
        }

        /// <summary>
        /// 获取日志器
        /// </summary>
        /// <param name="logFilePath">路径。如  2021\\06\\03\\20210603_debug.db</param>
        /// <returns></returns>
        public static DbWriter GetOrCreateLogWriter(string logFilePath)
        {
            string logFileName = Path.GetFileName(logFilePath);
            if (WriterPool.ContainsKey(logFileName))
            {
                WriterPool[logFileName].ActivityTime = DateTime.Now;
                return WriterPool[logFileName];
            }
            try
            {
                DbWriter writer = new DbWriter(GetConnectionStringByLogType(logFilePath));
                //判断数据是否初始化。若无，则进行初始化
                int _tableCount = writer.GetTableCount();
                if (_tableCount !=2 )
                {
                    writer.CreateDatabase();
                }

                writer.ActivityTime = DateTime.Now;
                WriterPool[logFileName] = writer;
                return writer;
            }
            catch(Exception exp) {
                //删除已生成失败数据库的文件
                string _fileUrl = LogConfig.LogDbPathRoot + logFilePath;
                if (Directory.Exists(_fileUrl))
                {
                    Directory.Delete(_fileUrl);
                }
                throw exp;
            }
        }

        #region 销毁过期日志器

        
        /// <summary>
        /// 销毁过期日志器
        /// </summary>
        public static void DestroyLogWriter()
        {
            try
            {
                //每隔3分钟，进行一次 过期的DatabaseWriter 清理 
                TimeSpan desSpan = DateTime.Now - DestroyTime;
                if (desSpan.TotalMinutes < 3)
                {
                    return;
                }

                DestroyTime = DateTime.Now;
                List<string> DestroyKeyList = new List<string>();
                foreach (KeyValuePair<string, DbWriter> kvp in WriterPool)
                {
                    // 清理活动时间超过销毁时间5分钟的的DatabaseWriter
                    TimeSpan span = DestroyTime - kvp.Value.ActivityTime;
                    if (span.TotalMinutes > 5)
                    {
                        DestroyKeyList.Add(kvp.Key);
                    }
                }
                //DatabaseWriter 清理
                foreach (string key in DestroyKeyList)
                {
                    DbWriter writer = WriterPool[key];
                    writer.Dispose();
                    WriterPool.Remove(key);
                }

            }
            catch { }

        }

        #endregion

        #region 销毁日志器

        /// <summary>
        /// 销毁日志器
        /// </summary>
        public static void DestroyAllWriter()
        {
            foreach (KeyValuePair<string, DbWriter> kvp in WriterPool)
            {
                DbWriter writer = WriterPool[kvp.Key];
                writer.Dispose();
                WriterPool.Remove(kvp.Key);
            }
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }

        #endregion



    }

}